<?php
namespace Buu\Modules\HaohaoceManager\Lib;
use Buu\Modules\HaohaoceManager\Lib\Dns;
use Buu\Modules\HaohaoceManager\Lib\Podinfo;
use Buu\Modules\HaohaoceManager\Lib\K8sModel;
use Buu\Modules\HaohaoceManager\Lib\Util;
use Doraemon\tools\Log;

class HhcService
{
	const DEFAULT_SERVER_IP = '172.26.4.31';
	const DIR_YAML_ORI = '/qa-ali-nfs/buu_haohaoce/hhc_k8s_yaml';
	const DIR_HHC_LOGS = '/qa-ali-nfs/buu_haohaoce/logs_bak/';
	const DIR_YAML_RUNNING = '/qa-ali-nfs/buu_haohaoce/hhc_k8s_yaml_running';
	const DIR_AFTERPULL_SCRIPT = '/qa-ali-nfs/buu_haohaoce/init_script/after_pull';
	const EXPIRE_ALERT_BEFORE_N_HOURS = 8;
	
	static public function get_suffix_start_end_num(){
		$dev_sign = is_file('/data/haohaoceManager_dev_sign') ? 1 : 0;
		if($dev_sign){
			return array(51,60);
		}else{
			return array(11,50);
		}
	}

	static public function getPods(){
		
		$podinfos = array();

		$pods = K8sModel::getPods();
		if(!empty($pods)){
			foreach ($pods as $pod_name => $pod_info) {
				$k8sPodInfos[$pod_name] = $pod_info;
			}
		}
		$svcs = K8sModel::getSvcs();
		if(!empty($svcs)){
			foreach ($svcs as $svc_name => $svc_info) {
				$k8sSvcInfos[$svc_name] = $svc_info;
			}
		}

		$podinfos = Podinfo::list_all();
		if(!empty($podinfos)){
			foreach ($podinfos as $pod_info) {
				$pod_id = $pod_info['pod_id'];
				$pod_name = $pod_info['pod_name'];
				$svc_name = $pod_info['svc_name'];

				if(isset($k8sPodInfos[$pod_name])){
					$pod_info = array_merge($pod_info,$k8sPodInfos[$pod_name]);
					unset($k8sPodInfos[$pod_name]);
				}

				if(isset($k8sSvcInfos[$svc_name])){
					$pod_info = array_merge($pod_info,$k8sSvcInfos[$svc_name]);
					unset($k8sSvcInfos[$svc_name]);
				}

				$podinfos[$pod_id] = $pod_info;
			}
		}
		return [
			'podInfos'=>$podinfos,
			'pod_unwanted' => $k8sPodInfos,
			'svc_unwanted' => $k8sSvcInfos,
		];
	}
	static public function cronCheckPodsStatus(){
		$rs = HhcService::getPods();


        foreach ($rs['podInfos'] as $pod_id => $row) {
        	//状态变化为运行中
        	if($row['status'] == Podinfo::STATUS_UNREADY){
            	if($row['pod_status'] == K8sModel::STATUS_RUNNING){
            		self::bindDomain($pod_id);

            		Podinfo::set_ready_by_podid($pod_id);
            		//发通知
            		K8sView::alert_pod_is_builded($row);
            	}
        	}else if($row['status'] == Podinfo::STATUS_READY){
        		$expire_timestamp = strtotime($row['expire']);
        		if($row['alerted']!= 1 && time() - $expire_timestamp < self::EXPIRE_ALERT_BEFORE_N_HOURS*30*60){
        			Podinfo::set_alerted_by_podid($pod_id);
					K8sView::alert_pod_will_be_expire($row);  
				}else if(time() > $expire_timestamp){
					K8sView::alert_pod_is_expired($row); 
					self::rm_slb_forward_rule($row['domain_suffix']);
					self::deletePod($pod_id , $row);
				}
        	}
        }

        //针对现有还存在的pod检查并加入到slb的转规则中。
        HhcService::add_slb_forward_rule();
	}
	//检查并添加实例到slb的转规则
	static public function add_slb_forward_rule(){
		$dns = new Dns();
		$aVserverIds_avail = $dns->list_slb_name2vserverids(Dns::SLB_REGION_ID , Dns::SLB_ID);
		$aRuleinfo_in_rules = $dns->list_slb_ruleinfo_in_rules(Dns::SLB_REGION_ID , Dns::SLB_ID , Dns::SLB_PORT);
		$aVserverIds_in_rules = array();
		foreach($aRuleinfo_in_rules as $row){
			$aVserverIds_in_rules[] = $row['vserver_id'];
		}
		

		foreach($aVserverIds_avail as $name => $vserver_id){
			if(!in_array($vserver_id , $aVserverIds_in_rules)){
				$pod_id = str_replace('hhc-be-','',explode('/',$name)[2]);
				//当前slb有一个占位用的默认service，但实际并不需要加入到转发规则中
				//todo 待去掉
				if(Podinfo::is_pod_id($pod_id)){
					$pod_info = Podinfo::get_by_podid($pod_id);
					$rule = $dns->format_slb_rule($pod_id , $pod_info['domain_suffix'] , $vserver_id);
					$dns->add_slb_forward_rule(Dns::SLB_REGION_ID , Dns::SLB_ID , Dns::SLB_PORT , $rule);
				}
			}
		}
		return true;
	}
	static public function rm_slb_forward_rule($domain_suffix){
		$dns = new Dns();
		$aRuleinfo_in_rules = $dns->list_slb_ruleinfo_in_rules(Dns::SLB_REGION_ID , Dns::SLB_ID , Dns::SLB_PORT);
		foreach($aRuleinfo_in_rules as $row){
			if($row['domain_suffix'] == $domain_suffix){
				$dns->rm_slb_forward_rule(Dns::SLB_REGION_ID , $row['rule_id']);
			}
		}
	}



	static public function getUsedDomainSuffix(){
		$list = Podinfo::list_all();
		$domain_suffixes = [];
		if(!empty($list)){
			foreach ($list as $pod_info) {
				$domain_suffixes[] = intval($pod_info['domain_suffix']);
			}
		}
		return $domain_suffixes;
	}
	static public function getPodInfo($pod_id , $ext = false){
		$pod_info = Podinfo::get_by_podid($pod_id);
		
		if($ext){
			$k8s_pod_info = K8sModel::getPodinfoByPodid($pod_info['pod_name']);
			$k8s_svc_info = K8sModel::getSvcinfoByid($pod_info['svc_name']);
			$pod_info = array_merge($pod_info , $k8s_pod_info , $k8s_svc_info);
		}

		return $pod_info;
	}
	static public function init_pod_id($admin_id){
		return $admin_id.'-'.date('YmdHis');
	}
	static private function _replace_registry_namespace($yaml){
		$dev_sign = is_file('/data/haohaoceManager_dev_sign') ? 1 : 0;
		if($dev_sign){
			// $yaml = str_replace('hhz-test' , 'hhztest' , $yaml);
		}
			$yaml = str_replace('hhztest/shaopu_' , 'hhz-test/' , $yaml);
		return $yaml;
	}
	static public function createPod($yaml_name ,$svc_yaml_path, $pod_id , $info , $pod_ext){
		
		Podinfo::add($pod_id , $info);

		// exists
		$yaml_path = self::DIR_YAML_ORI.'/'.$yaml_name;
		$svc_yaml_path = self::DIR_YAML_ORI.'/'.$svc_yaml_path;
		//copy pod yaml
		$yaml = file_get_contents($yaml_path);
		$yaml = str_replace('{pod_id}' , $pod_id , $yaml);
		$yaml = self::_replace_registry_namespace($yaml);
		foreach ($pod_ext as $key => $value) {
			$yaml = str_replace('{'.$key.'}' , $value , $yaml);
		}
		if(!empty($info['env'])){
			foreach ($info['env'] as $key => $value) {
				$yaml = str_replace('{env_'.$key.'}' , $value , $yaml);		
			}
		}
		$running_yaml_path = self::DIR_YAML_RUNNING.'/'.$pod_id.'.yaml';
		file_put_contents($running_yaml_path , $yaml);

		//copy svc yaml
		$yaml = file_get_contents($svc_yaml_path);
		$yaml = str_replace('{pod_id}' , $pod_id , $yaml);
		$running_yaml_svc_path = self::DIR_YAML_RUNNING.'/'.$pod_id.'_svc.yaml';
		file_put_contents($running_yaml_svc_path , $yaml);

		
		//create pod and svc
		$time = time();
		K8sView::running_log('start creating pod');
		$rs = K8sModel::createPod($running_yaml_path , $pod_name);
		K8sView::running_log('time:'.(time()-$time));
		if(!$rs){
			K8sView::running_log("error:  ".$rs);
			return false;
		}
		K8sView::running_log("create pod success~");


		//create svc
		$time = time();
		K8sView::running_log('start creating svc');
		$rs = K8sModel::createSvc($running_yaml_svc_path , $svc_name);
		K8sView::running_log('time:'.(time()-$time));

		if(!$rs){
			K8sView::running_log("error:  ".$rs);
			K8sModel::deletePod($running_yaml_path);
			return false;
		}
		K8sView::running_log("create svc success~");

		//创建日志目录
		mkdir(self::DIR_HHC_LOGS.$pod_id , 0777 , true);

		$info = [];
		$info['pod_name'] = $pod_name;
		$info['svc_name'] = $svc_name;
		$info['create_time'] = time();
		Podinfo::set_by_podid($pod_id , $info);

		return $rs;
	}
	static public function bindDomain($pod_id){
		$confs = Util::read_conf();
		$pod_info = HhcService::getPodInfo($pod_id , true);
		$pod_conf = $confs[$pod_info['pod_type']];
		$dns = new Dns();
		$root_domain = 'haohaoce.com';

		if(isset($pod_conf['domains'])){
			foreach ($pod_conf['domains'] as $domain){
				$domain = str_replace('{suffix}' , $pod_info['domain_suffix'] , $domain);
				$dns->bind(
					$domain,
					$root_domain , 
					$pod_info['svc_external_ip']
				);
			}
		}

		Util::add2domainList($pod_info['pod_id'] , $pod_info['domain_suffix']);
		return;
	}
	static public function unbindDomain($pod_id){
		$confs = Util::read_conf();
		$pod_info = HhcService::getPodInfo($pod_id , true);
		$pod_conf = $confs[$pod_info['pod_type']];
		$root_domain = 'haohaoce.com';

		$dns = new Dns();
		if(isset($pod_conf['domains'])){
			foreach ($pod_conf['domains'] as $domain){
				$domain = str_replace('{suffix}' , $pod_info['domain_suffix'] , $domain);
				$dns->del($domain , $root_domain);
			}
		}
		return;
	}
	static public function delay_expire_by_podid($pod_id){
		return Podinfo::delay_expire_by_podid($pod_id);
	}

	static public function testPod($cmd){
		return self::_run_cmd($cmd);
	}
	static public function deletePod($pod_id ){

		self::log('deletepod '.$pod_id.' '.time().' start');

		$confs = Util::read_conf();
		$pod_info = HhcService::getPodInfo($pod_id);
		self::log('deletepod '.$pod_id.' '.time().' rm_slb_forward_rule');

		self::rm_slb_forward_rule($pod_info['domain_suffix']);
		self::log('deletepod '.$pod_id.' '.time().' rm_slb_forward_rule');

        Util::delFromDomainList($pod_info['pod_id'] , $pod_info['domain_suffix']);
		self::log('deletepod '.$pod_id.' '.time().' delFromDomainList');

		try {
			//解绑域名
			$pod_info = Podinfo::get_by_podid($pod_id);
			$pod_conf = $confs[$pod_info['pod_type']];

			//域名都指向8.25 ，所以不需要删除
			// self::unbindDomain($pod_id);

			//删除pod
			$running_yaml_path = self::DIR_YAML_RUNNING.'/'.$pod_id.'.yaml';
			$rs = K8sModel::deletePod($running_yaml_path);
			if(!$rs){
				self::log("del_pod_fail: ".$rs);
			}else{
				unlink($running_yaml_path);
			}
			self::log('deletepod '.$pod_id.' '.time().' deletePod');

			//删除service
			$running_svc_yaml_path = self::DIR_YAML_RUNNING.'/'.$pod_id.'_svc.yaml';
			$rs = K8sModel::deleteSvc($running_svc_yaml_path);		
			if(!$rs){
				self::log("del_svc_fail: ".$rs);
			}else{
				unlink($running_svc_yaml_path);
			}
			self::log('deletepod '.$pod_id.' '.time().' deletePod');

			//删除描述文件
			Podinfo::del_by_podid($pod_id);
			//删除分支文件
			$running_branch_path = self::DIR_YAML_RUNNING.'/'.$pod_id.'-branch.json';
			if(is_file($running_branch_path)){
				unlink($running_branch_path);
			}

			//删除日志目录
			$cmd = 'rm -rf '.self::DIR_HHC_LOGS.$pod_id;
			self::_run_cmd($cmd);

		} catch (Exception $e) {
			return false;
		}
		return true;
	}
	static private function _getCurrentBranch($pod_name ,$container_name, $project_dir){
		$cmd = 'cd /data/wwwroot/'.$project_dir.'/;git status';
		
		$rs = K8sModel::execByPodname($pod_name ,$container_name, $cmd);
		
		preg_match('(origin[^\s\']+)' ,$rs , $b);
		return $b[0];
	}
	static public function getCurrentBranch($pod_id ,$container_name, $project_dir){
		$pod_info = K8sModel::getPodinfoByPodid($pod_id);
		$pod_name = $pod_info['pod_name'];
		return self::_getCurrentBranch($pod_name ,$container_name, $project_dir);
	}
	static public function checkBranches($pod_id , $pod_name){
		$branchFilePath = self::DIR_YAML_RUNNING.'/'.$pod_id.'-branch.json';
		$branches = array();
		
		if(is_file($branchFilePath)){
			$branches = json_decode(file_get_contents($branchFilePath) , 1);
			var_dump($branches);
			if(!empty($branches)){

				foreach ($branches as $project_dir => $branch) {
					$currentBranch = self::_getCurrentBranch($pod_name , $project_dir);
					echo 'currentBranch:'.$currentBranches."\n";
					if($currentBranch != $branch){
						echo 'switch to:'.$branch."\n";
						$rs = self::_switchBranch($pod_name , $project_dir , $branch);
						if($rs !== true){
							self::log($pod_id.' switch branch '.$project_dir.' fail:'.$rs);
						}
					}
				}
			}
		}
	}
	static private function _after_pull($pod_name , $container_name , $project_dir){
		$after_pull_script_path = self::DIR_AFTERPULL_SCRIPT.'/'.$project_dir.'.sh';
		if(is_file($after_pull_script_path)){
			$cmd = 'cd /data/wwwroot/;/bin/bash '.$after_pull_script_path.' >> /data/after_pull.log';
			$rs = K8sModel::execByPodname($pod_name , $container_name , $cmd);
		}
	}
	static private function _switchBranch($pod_name , $container_name , $project_dir , $branch){
		if($branch == 'remotes/origin/HEAD -> origin/master'){
			$branch = 'master';
		}
		if(substr($branch , 0 , 8)!='remotes/'){
			$branch = 'remotes/origin/'.str_replace('origin/' , '',$branch);
		}
		$dest_branch = str_replace('remotes/origin/','',$branch);
		$cmd = 'cd /data/wwwroot/'.$project_dir.'/;git reset --hard;git checkout -B '.$dest_branch.' '.$branch ;
		$rs_switch = K8sModel::execByPodname($pod_name , $container_name , $cmd);

		$cmd = 'cd /data/wwwroot/'.$project_dir.'/;git status';
		$rs = K8sModel::execByPodname($pod_name , $container_name , $cmd);

		if(substr($rs , 0 , 10+strlen($dest_branch)) == 'On branch '.$dest_branch){
			self::_after_pull($pod_name , $container_name , $project_dir);
			return true;
		}else{
			return $rs_switch;
		}
	}
	static public function switchBranch($pod_id , $container_name, $project_dir , $branch){
		//记录指定的各分支
		$branchFilePath = self::DIR_YAML_RUNNING.'/'.$pod_id.'-branch.json';
		$currentBranches = array();
		if(is_file($branchFilePath))
			$currentBranches = (array)json_decode(file_get_contents($branchFilePath) , 1);
		$currentBranches[$container_name][$project_dir] = $branch;
		file_put_contents($branchFilePath , json_encode($currentBranches));


		$pod_info = K8sModel::getPodinfoByPodid($pod_id , true);
		if($pod_info['pod_status'] == K8sModel::STATUS_RUNNING){
			$pod_name = $pod_info['pod_name'];
			self::_switchBranch($pod_name , $container_name , $project_dir , $branch);
		}
		return true;
	}
	static public function pullCode($pod_name , $container_name){
		//git pull时将结果输出到/dev/null，所以只有出现错误时才会打印内容，可通过是否输出为空判断是否正常执行
		
		$cmd = 'bash /qa-ali-nfs/buu_haohaoce/init_script/hhc_wwwroot_pull.sh';
		$rs = K8sModel::execByPodname($pod_name , $container_name , $cmd);
		if(empty(trim($rs))){
			return true;
		}else{
			return $rs;
		}
	}

	
	static private function _run_cmd($cmd){
		$fp = popen($cmd , 'r');
		while ($str = fread($fp , 4096)) {
			$rs.=$str;
		};
		return $rs;
	}
	static private function log($msg){
		Log::debug($msg);
	}
	static private function running_log($msg){
		echo $msg ."<br/>";
	}
}
